package thread;
//单例模式（饿汉模式和懒汉模式）
class SingletonHungry{
    private static SingletonHungry instance = new SingletonHungry();
    //将构造函数设置为private
    private SingletonHungry() {}
    //
    public static SingletonHungry getInstance(){
        return instance;
    }
}

//多线程不安全版本
class SingletonLazy1{
    private static SingletonLazy1 instance = null;

    private SingletonLazy1(){}

    public static SingletonLazy1 getInstance(){
        if(instance == null){
            instance = new SingletonLazy1();
        }
        return instance;
    }
}

//多线程安全版本
class SingletonLazy2{
    private volatile static SingletonLazy2 instance = null;

    private SingletonLazy2(){}

    public synchronized static SingletonLazy2 getInstance(){
        if(instance == null){
            instance = new SingletonLazy2();
        }
        return instance;
    }
}

//多线程安全版本（改进版）
class SingletonLazy3{
    private volatile static SingletonLazy3 instance = null;
    //避免类外部实例化对象
    private SingletonLazy3(){}

    public static SingletonLazy3 getInstance(){
        //对象创建以后，避免频繁的加锁解锁消耗资源
        if(instance == null){
            //加锁，保证第一次创建对象时线程安全
            synchronized (SingletonLazy3.class){
                //检查对象是否已经创建
                if(instance == null){
                    instance = new SingletonLazy3();
                }
            }
        }

        return instance;
    }
}

public class ThreadDemo13 {
    public static void main(String[] args) {
        SingletonHungry instance = SingletonHungry.getInstance();
        System.out.println(instance);
        //构造函数为私有，不能在类外实例化对象
        //SingletonHungry instance1 = new SingletonHungry();

        //SingletonLazy3 instance1 = SingletonLazy3.getInstance();

        //SingletonLazy3 instance2 = new SingletonLazy3();

        Thread[] threads = new Thread[10];
        for(int i = 0; i < 10; i++){
            threads[i] = new Thread(()->{
                SingletonLazy3 singleton = SingletonLazy3.getInstance();
                System.out.println(singleton);
            });

            threads[i].start();
        }

    }

}
